﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using HSDc.RingleFlow.Api.Service;
using HSDc.RingleFlow.Api.Kernel.History;
using HSDc.RingleFlow.Kernel.DBPersit.Dao;
using HSDc.RingleFlow.Api.Kernel;
using HSDc.RingleFlow.Kernel.DBPersit.PersitEnum;
//using NUnit.Framework;

namespace HSDc.RingleFlow.Kernel.DBPersit
{
    //[TestFixture]
    public class HistoryServiceImpl: IHistoryService
    {
        AuditVdb IHistoryService.RetrieveAuditInfo(string ProcessInstanceID)
        {
            int piRealId = 0;
            AuditVdb vdb = new AuditVdb();
            HistoryServiceDao dao = new HistoryServiceDao();
            AuditType type = FillProcessInstance(vdb, dao, ProcessInstanceID, ref piRealId);
            switch (type)
            {
                case AuditType.Active:
                    FillActiveInstance(vdb, dao, ProcessInstanceID, piRealId);
                    break;
                case AuditType.History:
                    FillHistoryInstance(vdb, dao, ProcessInstanceID, piRealId);
                    break;
            }
            return vdb;
        }

        private void FillActiveInstance(AuditVdb vdb, HistoryServiceDao dao, string id, int realId)
        {
            FillProcessInstanceVariable(vdb, dao, id);
            FillStage(vdb, dao, id, realId);
        }

        private void FillHistoryInstance(AuditVdb vdb, HistoryServiceDao dao, string id, int realId)
        {
            FillProcessInstanceVariableHistory(vdb, dao, id);
            FillStageHistory(vdb, dao, id, realId);
        }

        #region FIll Process Instance
        private AuditType FillProcessInstance(AuditVdb vdb, HistoryServiceDao dao, string ProcessInstanceID, ref int piRealId)
        {
            ProcessInstanceDto dto = dao.RetrieveProcessInstance(ProcessInstanceID);
            if (dto != null)
            {
                vdb.ProcessInstance.AddProcessInstanceRow(dto.ProcessInstance_GUID,
                    dto.ProcessInstance_Start, DateTime.Now, string.Empty,
                    ((ExecutionState)dto.ProcessInstance_Status).ToString(),
                    string.Empty);
                AuditVdb.ProcessInstanceRow piRow = vdb.ProcessInstance.FindByInstanceID(ProcessInstanceID);
                if (dto.ProcessInstance_End != null)
                    piRow.InstanceEndDate = dto.ProcessInstance_End.Value;
                else
                    piRow.SetInstanceEndDateNull();
                FillProcessDefinition(vdb, dao, piRow.InstanceID, dto.ProcessInstance_Belong_Definition);
                piRealId = dto.ProcessInstance_ID;
                return AuditType.Active;
            }
            return FillProcessInstanceHistory(vdb, dao, ProcessInstanceID, ref piRealId);
        }
        private AuditType FillProcessInstanceHistory(AuditVdb vdb, HistoryServiceDao dao, string ProcessInstanceID, ref int piRealId)
        {
            ProcessInstanceHistoryDto dto = dao.RetrieveProcessInstanceHistory(ProcessInstanceID);
            if (dto != null)
            {
                vdb.ProcessInstance.AddProcessInstanceRow(dto.ProcessInstance_GUID,
                    dto.ProcessInstance_Start, DateTime.Now, string.Empty,
                    ((ExecutionState)dto.ProcessInstance_Status).ToString(),
                    string.Empty);
                AuditVdb.ProcessInstanceRow piRow = vdb.ProcessInstance.FindByInstanceID(ProcessInstanceID);
                if (dto.ProcessInstance_End != null)
                    piRow.InstanceEndDate = dto.ProcessInstance_End.Value;
                else
                    piRow.SetInstanceEndDateNull();
                FillProcessDefinition(vdb, dao, piRow.InstanceID, dto.ProcessInstance_Belong_Definition);
                piRealId = dto.ProcessInstance_ID;
                return AuditType.History;
            }
            return AuditType.None;
        }

        private void FillProcessDefinition(AuditVdb vdb, HistoryServiceDao dao, string id, int pdid)
        {
            ProcessDefinitionDto dto = dao.RetrieveProcessDefinition(pdid);
            AuditVdb.ProcessInstanceRow piRow = vdb.ProcessInstance.FindByInstanceID(id);
            piRow.ProcessDefinitionID = dto.Definition_GUID;
            piRow.ProcessDefinitionName = dto.Definition_Name + ", Version " + dto.Definition_Version.ToString();
        }
        #endregion

        #region Fill Process Instance Variable
        private void FillProcessInstanceVariable(AuditVdb vdb, HistoryServiceDao dao, string id)
        {
            List<InstanceVariableDto> dtos = dao.RetrieveProcessInstanceVariable(id);
            foreach (InstanceVariableDto dto in dtos)
            {
                vdb.ProcessInstanceVariables.AddProcessInstanceVariablesRow(
                    vdb.ProcessInstance.FindByInstanceID(id), dto.Variable_Name, dto.Variable_Value);
            }
        }

        private void FillProcessInstanceVariableHistory(AuditVdb vdb, HistoryServiceDao dao, string id)
        {
            List<InstanceVariableHistoryDto> dtos = dao.RetrieveProcessInstanceVariableHistory(id);
            foreach (InstanceVariableHistoryDto dto in dtos)
            {
                vdb.ProcessInstanceVariables.AddProcessInstanceVariablesRow(
                    vdb.ProcessInstance.FindByInstanceID(id), dto.Variable_Name, dto.Variable_Value);
            }
        }
        #endregion

        #region Fill Stage
        private void FillStage(AuditVdb vdb, HistoryServiceDao dao, string piid, int pirealid)
        {
            List<ActivityInstanceDto> dtos = dao.RetrieveActivityInstance(pirealid);
            int count = 0;
            foreach (var dto in dtos)
            {
                count ++;
                ProcessActivityDto padto = dao.RetrieveActivity(dto.ActivityInstance_Belong_Actvity);
                vdb.Stage.AddStageRow(dto.ActivityInstance_GUID, count, padto.Activity_Name, 
                    dto.ActivityInstance_Start,
                    DateTime.Now, vdb.ProcessInstance.FindByInstanceID(piid),
                    padto.Activity_CLASS.Substring(padto.Activity_CLASS.LastIndexOf('.')+1), dto.ActivityInstance_Assignee,
                    ((TaskState)dto.ActivityInstance_Status).ToString());
                AuditVdb.StageRow sRow = vdb.Stage.FindByStageID(dto.ActivityInstance_GUID);
                if (dto.ActivityInstance_End.HasValue)
                    sRow.StageEndDate = dto.ActivityInstance_End.Value;
                else
                    sRow.SetStageEndDateNull();
                FillStageVariable(vdb, dao, dto.ActivityInstance_GUID);
            }
        }

        private void FillStageHistory(AuditVdb vdb, HistoryServiceDao dao, string piid, int pirealid)
        {
            List<ActivityInstanceHistoryDto> dtos = dao.RetrieveActivityInstanceHistory(pirealid);
            int count = 0;
            foreach (var dto in dtos)
            {
                count++;
                ProcessActivityDto padto = dao.RetrieveActivity(dto.ActivityInstance_Belong_Actvity);
                vdb.Stage.AddStageRow(dto.ActivityInstance_GUID, count, padto.Activity_Name,
                    dto.ActivityInstance_Start,
                    DateTime.Now, vdb.ProcessInstance.FindByInstanceID(piid),
                    padto.Activity_CLASS.Substring(padto.Activity_CLASS.LastIndexOf('.') + 1), dto.ActivityInstance_Assignee,
                    ((TaskState)dto.ActivityInstance_Status).ToString());
                AuditVdb.StageRow sRow = vdb.Stage.FindByStageID(dto.ActivityInstance_GUID);
                if (dto.ActivityInstance_End.HasValue)
                    sRow.StageEndDate = dto.ActivityInstance_End.Value;
                else
                    sRow.SetStageEndDateNull();
                FillStageVariableHistory(vdb, dao, dto.ActivityInstance_GUID);
            }
        }

        #endregion

        #region Fill Stage Variable
        private void FillStageVariable(AuditVdb vdb, HistoryServiceDao dao, string acid)
        {
            List<InstanceVariableDto> dtos = dao.RetrieveActivityInstanceVariable(acid);
            foreach (InstanceVariableDto dto in dtos)
            {
                vdb.StageVariables.AddStageVariablesRow(
                    vdb.Stage.FindByStageID(acid), dto.Variable_Name, dto.Variable_Value);
            }
        }

        private void FillStageVariableHistory(AuditVdb vdb, HistoryServiceDao dao, string acid)
        {
            List<InstanceVariableHistoryDto> dtos = dao.RetrieveActivityInstanceVariableHistory(acid);
            foreach (InstanceVariableHistoryDto dto in dtos)
            {
                vdb.StageVariables.AddStageVariablesRow(
                    vdb.Stage.FindByStageID(acid), dto.Variable_Name, dto.Variable_Value);
            }
        }
        #endregion

        //[Test]
        //public void TestRetrieveAuditInfoFromHistory()
        //{
        //    string input = "2edaed22-be21-45c0-a325-7624320f9189";
        //    IHistoryService service = new HistoryServiceImpl();
        //    AuditVdb vdb = service.RetrieveAuditInfo(input);
        //    Console.WriteLine(vdb.GetXml());
        //}

        //[Test]
        //public void TestRetrieveAuditInfoFromActive()
        //{
        //    string input = "e06dd914-c035-4b9a-953a-676f44a8213b";
        //    IHistoryService service = new HistoryServiceImpl();
        //    AuditVdb vdb = service.RetrieveAuditInfo(input);
        //    Console.WriteLine(vdb.GetXml());
        //}
    }
}
